package rpc_netty.RegistryImpl;

import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rpc_1.interfaces.ServiceRegisrty;
import rpc_netty.LoadBalancerImpl.RandomLoadBalancer;
import rpc_netty.NacosUtils.NacosUtil;
import rpc_netty.interfaces.LoadBalancer;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

public class NacosServiceRegistry implements ServiceRegisrty {
    private static final Logger logger= LoggerFactory.getLogger(NacosServiceRegistry.class);

    private static String SERVER_ADDR;
    private static NamingService namingService;
    private static ConfigService configService;

    //负载均衡器，在拿到的服务列表中挑选一个，返回给客户端使用
    private  LoadBalancer loadBalancer;


    public NacosServiceRegistry(LoadBalancer loadBalancer){
        if (loadBalancer==null)
            this.loadBalancer=new RandomLoadBalancer();
        else{
            this.loadBalancer=loadBalancer;
        }
    }

    public NacosServiceRegistry(){
        this.loadBalancer=new RandomLoadBalancer();
    }

    @Override
    public void SetAdd_And_Create(String addr){
        this.SERVER_ADDR=addr;
        try {
            namingService = NamingFactory.createNamingService(SERVER_ADDR);
            configService= NacosFactory.createConfigService(SERVER_ADDR);
        } catch (NacosException e) {
            logger.error("error when connecting to the nacos",e);
            e.printStackTrace();
        }
    }


    public void setLoadBalancer(LoadBalancer loadBalancer){
        this.loadBalancer=loadBalancer;
    }

    /*
    服务端调用，注册一个地址和服务名称到注册中心
     */
    @Override
    public void register(String serviceName, InetSocketAddress inetSocketAddress) {
        try {
            namingService.registerInstance(serviceName,inetSocketAddress.getHostName(),inetSocketAddress.getPort());
            long timestamp = System.currentTimeMillis();
            configService.publishConfig(serviceName, inetSocketAddress.getHostName()+":"+inetSocketAddress.getPort(), timestamp + "");
        } catch (NacosException e) {
            logger.error("error when register the service to nacos",e);
            e.printStackTrace();
        }
    }

    /*
    客户端调用，从注册中心获得对应的服务地址
    函数会根据不同的负载均衡策略，选择一个地址返回
     */
    @Override
    public InetSocketAddress lookupService(String serviceName) {
        try {
            List<Instance> allInstances = NacosUtil.getAllInstances(serviceName);
            Instance instance= loadBalancer.select(allInstances);
            return new InetSocketAddress(instance.getIp(),instance.getPort());
        } catch (NacosException e) {
            logger.error("error when get the service",e);
            e.printStackTrace();
        }
        return null;
    }
}
